//    Openbravo POS is a point of sales application designed for touch screens.
//    Copyright (C) 2007-2009 Openbravo, S.L.
//    http://www.openbravo.com/product/pos
//
//    This file is part of Openbravo POS.
//
//    Openbravo POS is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    Openbravo POS is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with Openbravo POS.  If not, see <http://www.gnu.org/licenses/>.
package com.openbravo.pos.printer;

import java.util.*;

import com.openbravo.pos.base.AppProperties;
import com.openbravo.pos.printer.printer.DevicePrinterPrinter;
import com.openbravo.pos.printer.screen.*;

import com.openbravo.pos.util.StringParser;
import java.awt.Component;
import java.util.logging.Level;
import java.util.logging.Logger;

import net.xeoh.plugins.base.PluginManager;
import net.xeoh.plugins.base.util.PluginManagerUtil;


public class DeviceTicket{

    private static Logger logger = Logger.getLogger("com.openbravo.pos.printer.DeviceTicket");

    private DeviceFiscalPrinter m_deviceFiscal;
    private DeviceDisplay m_devicedisplay;
    private DevicePrinter m_nullprinter;
    private Map<String, DevicePrinter> m_deviceprinters;
    private List<DevicePrinter> m_deviceprinterslist;
      
    
    /** Creates a new instance of DeviceTicket */
    public DeviceTicket() {
        // Una impresora solo de pantalla.

        m_deviceFiscal = new DeviceFiscalPrinterNull();

        m_devicedisplay = new DeviceDisplayNull();

        m_nullprinter = new DevicePrinterNull();
        m_deviceprinters = new HashMap<String, DevicePrinter>();
        m_deviceprinterslist = new ArrayList<DevicePrinter>();

        DevicePrinter p = new DevicePrinterPanel();
        m_deviceprinters.put("1", p);
        m_deviceprinterslist.add(p);
    }

    public DeviceTicket(PluginManager pmf,Component parent, AppProperties props) {

        PrinterWritterPool pws = new PrinterWritterPool();

        PluginManagerUtil pmu = new PluginManagerUtil(pmf);
        
        
        // La impresora fiscal
        StringParser sf = new StringParser(props.getProperty("machine.fiscalprinter"));
        String sFiscalType = sf.nextToken(':');
        String sFiscalParam1 = sf.nextToken(',');
        try {
        	final Collection<DeviceFiscalPrinter> plugins = pmu.getPlugins(DeviceFiscalPrinter.class);
        	for(DeviceFiscalPrinter fiscalPrinter:plugins){
        		if(fiscalPrinter.getFiscalPrinterType().equals(sFiscalType)){
        			m_deviceFiscal=fiscalPrinter;
        			m_deviceFiscal.init(sFiscalParam1);
        			break;
        		}
        			
        	}
            if(m_deviceFiscal==null) {
                m_deviceFiscal = new DeviceFiscalPrinterNull();
            }
        } catch (TicketPrinterException e) {
            m_deviceFiscal = new DeviceFiscalPrinterNull(e.getMessage());
        }

        // El visor
        StringParser sd = new StringParser(props.getProperty("machine.display"));
        String sDisplayType = sd.nextToken(':');
        String sDisplayParam1 = sd.nextToken(',');
        String sDisplayParam2 = sd.nextToken(',');

        // compatibilidad hacia atras.
        if ("serial".equals(sDisplayType) || "rxtx".equals(sDisplayType) || "file".equals(sDisplayType)) {
            sDisplayParam2 = sDisplayParam1;
            sDisplayParam1 = sDisplayType;
            sDisplayType = "epson";
        }
        try {
            if ("screen".equals(sDisplayType)) {
                m_devicedisplay = new DeviceDisplayPanel();
            } else if ("window".equals(sDisplayType)) {
                m_devicedisplay = new DeviceDisplayWindow();
            } else {
            	final Collection<DeviceDisplay> plugins = pmu.getPlugins(DeviceDisplay.class);
            	for(DeviceDisplay display:plugins){
            		if(display.getDisplayType().equals(sDisplayType)){
            			m_devicedisplay=display;
            			m_devicedisplay.init(sDisplayParam1, sDisplayParam2);
            			break;
            		}	
            	}
            } 
            if(m_devicedisplay==null){
                m_devicedisplay = new DeviceDisplayNull();
            }
        } catch (TicketPrinterException e) {
            logger.log(Level.WARNING, e.getMessage(), e);
            m_devicedisplay = new DeviceDisplayNull(e.getMessage());
        }

        m_nullprinter = new DevicePrinterNull();
        m_deviceprinters = new HashMap<String, DevicePrinter>();
        m_deviceprinterslist = new ArrayList<DevicePrinter>();

        // Empezamos a iterar por las impresoras...
        int iPrinterIndex = 1;
        String sPrinterIndex = Integer.toString(iPrinterIndex);
        String sprinter = props.getProperty("machine.printer");

        while (sprinter != null && !"".equals(sprinter)) {

            StringParser sp = new StringParser(sprinter);
            String sPrinterType = sp.nextToken(':');
            String sPrinterParam1 = sp.nextToken(',');
            String sPrinterParam2 = sp.nextToken(',');

            /* compatibilidad hacia atras.
            if ("serial".equals(sPrinterType) || "rxtx".equals(sPrinterType) || "file".equals(sPrinterType)) {
                sPrinterParam2 = sPrinterParam1;
                sPrinterParam1 = sPrinterType;
                sPrinterType = "epson";
            }*/

            try {
                if ("screen".equals(sPrinterType)) {
                    addPrinter(sPrinterIndex, new DevicePrinterPanel());
                } else if ("printer".equals(sPrinterType)) {

                    // backward compatibility
                    if (sPrinterParam2 == null || sPrinterParam2.equals("") || sPrinterParam2.equals("true")) {
                        sPrinterParam2 = "receipt";
                    } else if (sPrinterParam2.equals("false")) {
                        sPrinterParam2 = "standard";
                    }

                    addPrinter(sPrinterIndex, new DevicePrinterPrinter(parent, sPrinterParam1,
                            Integer.parseInt(props.getProperty("paper." + sPrinterParam2 + ".x")),
                            Integer.parseInt(props.getProperty("paper." + sPrinterParam2 + ".y")),
                            Integer.parseInt(props.getProperty("paper." + sPrinterParam2 + ".width")),
                            Integer.parseInt(props.getProperty("paper." + sPrinterParam2 + ".height")),
                            props.getProperty("paper." + sPrinterParam2 + ".mediasizename")
                            ));
                }else{
                	final Collection<DevicePrinter> plugins = pmu.getPlugins(DevicePrinter.class);
                	for(DevicePrinter printer:plugins){
                		if(printer.getPrinterType().equals(sPrinterType)){
                			addPrinter(sPrinterIndex,printer.init(sPrinterParam1, sPrinterParam2));
                			break;
                		}	
                	}
                }
            } catch (TicketPrinterException e) {
                logger.log(Level.WARNING, e.getMessage(), e);
            }

            // siguiente impresora...
            iPrinterIndex++;
            sPrinterIndex = Integer.toString(iPrinterIndex);
            sprinter = props.getProperty("machine.printer." + sPrinterIndex);
        }
    }

    private void addPrinter(String sPrinterIndex, DevicePrinter p) {
        m_deviceprinters.put(sPrinterIndex, p);
        m_deviceprinterslist.add(p);
    }

    // Impresora fiscal
    public DeviceFiscalPrinter getFiscalPrinter() {
        return m_deviceFiscal;
    }
    // Display
    public DeviceDisplay getDeviceDisplay() {
        return m_devicedisplay;
    }
    // Receipt printers
    public DevicePrinter getDevicePrinter(String key) {
        DevicePrinter printer = m_deviceprinters.get(key);
        return printer == null ? m_nullprinter : printer;
    }

    public List<DevicePrinter> getDevicePrinterAll() {
        return m_deviceprinterslist;
    }
    
}
